/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

// DlgMain.cpp : implementation file

#include "stdafx.h"
#include "CHScanner.h"
#include "DlgMain.h"

#include <afxpriv.h>	///< included for WM_KICKIDLE message

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//---------------------------------------------------------------------------

#define MI_MACLookup		1
#define MI_MCASTLookup		2
#define MI_Config			3
#define MI_ResetLayout		4
#define MI_UpdateCheck		5
#define MI_ImportGeoIP      6

//---------------------------------------------------------------------------

DlgMain::DlgMain(CWnd* pParent /*=NULL*/) : CDialog(DlgMain::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	hIconMinimize = NULL;
	hBmpGPL = NULL;

	config.Initialize();
	skin.Initialize();

	dlgSplash     = NULL;
	dlgMap        = NULL;
	dlgMsg        = NULL;
	dlgDetails    = NULL;

	firstTime = false;

	applicationPath.Empty();
	eventLog = NULL;

	autoRunMode = __rmNormal;
	autoRunParameter.Empty();
	autoRunTime = -1;

	lastScanType = __lstNone;

	exitCode = AUTO_END_SUCCESS;
	exitRunningTime.Empty();
	exitExportedFile.Empty();

	interfaceCount = 0;

	xHuntParams.Initialize();
	xHuntParams.xIpLocator = &ipLocatorBin;
}

DlgMain::~DlgMain(void)
{
	vendorList.Clear();
	mcast4NamesList.Clear();
	portDescList.Clear();

	DestroyUI();

	if(hIconMinimize!=NULL){
		DeleteObject(hIconMinimize);
		hIconMinimize = NULL;
	}
	if(hBmpGPL!=NULL){
		DeleteObject(hBmpGPL);
		hBmpGPL = NULL;
	}
}

//---------------------------------------------------------------------------

void DlgMain::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_BTN_SCAN, uiBtnScan);
	DDX_Control(pDX, IDC_BTN_STOP, uiBtnStop);
	DDX_Control(pDX, IDC_BTN_EXML, uiBtnExpXML);
	DDX_Control(pDX, IDC_BTN_HELP, uiBtnHelp);
	DDX_Control(pDX, IDC_BTN_CLOSE, uiBtnClose);
	DDX_Control(pDX, IDC_BTN_SNIFF, uiBtnSniff);
	DDX_Control(pDX, IDC_STA_INFO, staInfo);
	DDX_Control(pDX, IDC_BTN_INTF, uiBtnIntf);
	DDX_Control(pDX, IDC_BTN_TOOLS, uiBtnTools);
	DDX_Control(pDX, IDC_BTN_MINIMIZE, uiBtnMinimize);
	DDX_Control(pDX, IDC_BTN_HUNT, uiBtnHunt);
	DDX_Control(pDX, IDC_BTN_GPL, uiBtnGPL);
	DDX_Control(pDX, IDC_STA_GPL, staGPL);
}

BEGIN_MESSAGE_MAP(DlgMain, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_BTN_SCAN,     OnBnClickedBtnScan)
	ON_BN_CLICKED(IDC_BTN_SNIFF,    OnBnClickedBtnSniff)
	ON_BN_CLICKED(IDC_BTN_HUNT,     &DlgMain::OnBnClickedBtnHunt)
	ON_BN_CLICKED(IDC_BTN_STOP,     OnBnClickedBtnStop)
	ON_BN_CLICKED(IDC_BTN_EXML,     OnBnClickedBtnExpXML)
	ON_BN_CLICKED(IDC_BTN_INTF,     &DlgMain::OnBnClickedBtnIntf)
	ON_BN_CLICKED(IDC_BTN_TOOLS,    &DlgMain::OnBnClickedBtnTools)
	ON_BN_CLICKED(IDC_BTN_HELP,     OnBnClickedBtnHelp)
	ON_BN_CLICKED(IDC_BTN_CLOSE,    OnBnClickedBtnClose)
	ON_BN_CLICKED(IDC_BTN_MINIMIZE, &DlgMain::OnBnClickedBtnMinimize)
	ON_BN_CLICKED(IDC_BTN_GPL,      &DlgMain::OnBnClickedBtnGPL)

	ON_WM_SHOWWINDOW()

	ON_MESSAGE(CHS_MSG_SCAN_START,              OnCmsStart)
	ON_MESSAGE(CHS_MSG_SCAN_DONE,               OnCmsDone)
	ON_MESSAGE(CHS_MSG_SCAN_SKIPPED,            OnCmsSkipped)
	ON_MESSAGE(CHS_MSG_SCAN_RANDOMIZE_ADDRLIST, OnCmsRandomizeAddrList)
	ON_MESSAGE(CHS_MSG_SCAN_SORT_ADDRLIST,      OnCmsSortAddrList)
	ON_MESSAGE(CHS_MSG_SCANPHASE_START,         OnCmsPhaseStart)
	ON_MESSAGE(CHS_MSG_SCANPHASE_DONE,          OnCmsPhaseDone)
	ON_MESSAGE(CHS_MSG_SCANPHASE_FAILED,        OnCmsPhaseFailed)
	ON_MESSAGE(CHS_MSG_SCANPHASE_SKIPPED,       OnCmsPhaseSkipped)
	ON_MESSAGE(CHS_MSG_AFTER_PHASE,             OnCmsAfterPhase)
	ON_MESSAGE(CHS_MSG_LIST_BUILDED,            OnCmsListBuilded)
	ON_MESSAGE(CHS_MSG_UPDATE_DATA,				OnCmsUpdateData)
	ON_MESSAGE(CHS_MSG_PACKETS_SENT,			OnCmsPacketsSent)
	ON_MESSAGE(CHS_MSG_METHOD_START,			OnCmsMethodStart)
	ON_MESSAGE(CHS_MSG_METHOD_ABORT,			OnCmsMethodAbort)
	ON_MESSAGE(CHS_MSG_SYSARPTAB_UPDATED,		OnCmsMethodSARPUpd)
	ON_MESSAGE(CHS_MSG_HUNT_MACHINE,            OnCmsHuntMachine)

	ON_MESSAGE(CHS_MSG_AUTORUN,                 OnCmsAutoRun)
	ON_MESSAGE(CHS_MSG_AUTOCLOSE,               OnCmsAutoClose)

	ON_MESSAGE(WM_KICKIDLE, OnKickIdle)

	ON_WM_HELPINFO()
	ON_WM_TIMER()
END_MESSAGE_MAP()

//---------------------------------------------------------------------------

BOOL DlgMain::OnInitDialog()
{
	CDialog::OnInitDialog();

	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	CString str;
	CString fullFileName;

	helpInfo.applicationPath = applicationPath;

	if(!CreateSplashDialog()){
		display.DisplayMessageBoxById(FAILED_TO_CREATE_USER_INTERFACE, MB_OK | MB_ICONERROR);
		exitCode = END_INIT_FAILED;
		EndDialog(FALSE);
		return FALSE;
	}

	dlgSplash->SetText(_T("Loading configuration"));
	LoadConfiguration();
	
	dlgSplash->SetText(_T("Loading current skin"));
	LoadCurrentSkin();

	dlgSplash->SetText(_T("Creating user interface"));
	if(!CreateUI()){
		display.DisplayMessageBoxById(FAILED_TO_CREATE_USER_INTERFACE, MB_OK | MB_ICONERROR);
		DestroySplashDialog();
		exitCode = END_INIT_FAILED;
		EndDialog(FALSE);
		return FALSE;
	}

	display.dlgMsg = dlgMsg;

	dlgSplash->SetText(_T("Loading scan configurations"));

	wcm.display = &display;
	wcm.applicationPath = applicationPath;
	wcm.Refresh();

	workCfg.Initialize();

	// Loading the list of vendors by MAC
	dlgSplash->SetText(_T("Loading vendor list"));

	str = applicationPath;
	str += _T("vendors.dat");
	if(!vendorList.LoadFromMyFile(str))
		display.DisplayStatusMessage(COULD_NOT_LOAD_VENDORS);

	if(dlgMap!=NULL)
		dlgMap->vendorList = &vendorList;
	if(dlgDetails!=NULL)
		dlgDetails->vendorList = &vendorList;

	// Loading the IPv4 multicast list
	dlgSplash->SetText(_T("Loading IPv4 multicast list"));

	str = applicationPath;
	str += _T("mcast4.dat");
	if(!mcast4NamesList.LoadFromMyFile(str))
		display.DisplayStatusMessage(COULD_NOT_LOAD_MCAST4);

	if(dlgMap!=NULL)
		dlgMap->mcast4List = &mcast4NamesList;
	if(dlgDetails!=NULL)
		dlgDetails->mcast4List = &mcast4NamesList;

	// Loading the assignment of ports and protocols
	dlgSplash->SetText(_T("Loading ports and protocols descriptions"));

	str = applicationPath;
	str += _T("ports.dat");
	if(!portDescList.LoadFromFile(str))
		display.DisplayStatusMessage(COULD_NOT_LOAD_PORTASSIGLIST);

	if(dlgMap!=NULL)
		dlgMap->portDescList = &portDescList;
	if(dlgDetails!=NULL)
		dlgDetails->portDescList = &portDescList;

	// display stuff
	str = GetProgramNameAndVersion();
	display.DisplayStatusMessage(str);

	ShowLoadedInfoCounters();

	switch(autoRunMode){
		case __rmNormal :
			str = _T("Quick start: click the \"Scan\" button and select a scan configuration.");
			display.DisplayStatusMessage(str);
			break;

		case __rmAutoScan :
			fullFileName = applicationPath;
			fullFileName += _T("Configs\\");
			fullFileName += autoRunParameter;
			if(!workCfg.LoadFromFile(fullFileName)){
				display.DisplayStatusMessageWithParamS(COULD_NOT_READ_CONFIG_FILE, autoRunParameter);
				exitCode = AUTO_END_COULDNOTLOADFILE;
				EndDialog(FALSE);
				return FALSE;
			}
			display.DisplayStatusMessageWithParamS(CONFIG_FILE_LOADED, autoRunParameter);
			break;

		case __rmPassive :
			workCfg.Initialize();
			workCfg.xPassiveMode = true;

			if(autoRunParameter.IsEmpty()) autoRunTime = 0;
			else{
				autoRunTime = StrToInt(autoRunParameter);
				if(autoRunTime<10 || autoRunTime>86400){
					// invalid ammount of time specified
					exitCode = AUTO_END_INVALID_RUN_TIME;
					EndDialog(FALSE);
					return FALSE;
				}
			}
			break;

		default :
			exitCode = AUTO_END_INVALID_PARAM;
			EndDialog(FALSE);
			return FALSE;
	}

	theScanner.applicationPath = applicationPath;
	theScanner.appCfg          = &config;

	dlgInterface.winPcap = theScanner.GetWinPcap();

	bool res;
	res = true;
	res &= popupMenu.AddMenuItem(MI_MACLookup,   _T("MAC Lookup"));
	res &= popupMenu.AddMenuItem(MI_MCASTLookup, _T("Multicast IPv4 Lookup"));
	res &= popupMenu.AddMenuItem(0,              _T(""));
	res &= popupMenu.AddMenuItem(MI_UpdateCheck, _T("Check for Updates"));
	res &= popupMenu.AddMenuItem(0,              _T(""));
	res &= popupMenu.AddMenuItem(MI_ImportGeoIP, _T("Import GeoIP Data"));
	res &= popupMenu.AddMenuItem(0,              _T(""));
	res &= popupMenu.AddMenuItem(MI_Config,      _T("Configuration"));
	res &= popupMenu.AddMenuItem(MI_ResetLayout, _T("Reset Layout"));
	if(res)
		res = popupMenu.Create();

//	if(!res){
//		EndDialog(FALSE);
//		return FALSE;
//	}



	// TODO: Add extra initialization here


	dlgSplash->SetText(_T("Done"));

	DestroySplashDialog();

	SetWorkInterfaceAndDisplayInfo();

	CWinApp *theApp;
	if(hIconMinimize==NULL){
		theApp = AfxGetApp();
		if(theApp!=NULL)
			hIconMinimize = theApp->LoadIcon(IDI_ICO_MINIMIZE);
	}
	uiBtnMinimize.SetIcon(hIconMinimize);
	if(hBmpGPL==NULL){
		theApp = AfxGetApp();
		if(theApp!=NULL)
			hBmpGPL = (HBITMAP)LoadImage(theApp->m_hInstance, MAKEINTRESOURCE(IDB_BMP_GPL), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
	}
	uiBtnGPL.SetBitmap(hBmpGPL);


	wcm.SetLocalIPandMask(theScanner.GetLocalIP(), theScanner.GetLocalIPMask());

	// here a message is posted to begin the scanning process
	PostMessage(CHS_MSG_AUTORUN, (WPARAM)0, (LPARAM)0);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

//---------------------------------------------------------------------------

void DlgMain::SetWorkInterfaceAndDisplayInfo(void)
{
	CString str;

	theScanner.defaultInterfaceName = configInterface.interfaceName;
	SetDisplayInformations();
	str = theScanner.GetIpInterfaceAdapterName();
	display.DisplayStatusMessage(str);

	configInterface.interfaceName = theScanner.GetInterfaceName();
	interfaceCount = theScanner.GetIpInterfaceCount();
	if(interfaceCount>1){
		uiBtnIntf.EnableWindow(TRUE);
	}
	else{
		uiBtnIntf.EnableWindow(FALSE);
	}

	Invalidate(TRUE);
	UpdateWindow();
}

//---------------------------------------------------------------------------

CString DlgMain::GetProgramNameAndVersion(void)
{
	CString str;

	str.Format(_T("%s\\CHScanner.exe"), applicationPath);
	versionReader.GetInternalData(str);

	str.Format(_T("%s ver.%s.%s (Build %s)"), versionReader.ProductName, versionReader.VersionNumber, versionReader.ReleaseNumber, versionReader.BuildNumber);

	return str;
}

void DlgMain::SetDisplayInformations(void)
{
	CString str;

	str  = GetProgramNameAndVersion();
	str += _T("\n");

	str += _T("http://calinradoni.blogspot.com");
	//str += _T("http://code.google.com/p/chscanner");
	str += _T("\n");

	str += _T("Author: Calin Radoni (calin.radoni at gmail.com)\n");
	str += utilsSO.GetOSFullNameEx();
	str += _T("\n");

	str += _T("IP Address: ");
	str += theScanner.GetLocalIPv4AddressAsString();
	str += _T(", ");
	str += theScanner.GetLocalIPv6AddressAsString();
	str += _T("\n");

	staInfo.SetWindowText(str);
	staInfo.changeTextColor = true;
	staInfo.textColor = skin.titleColor;

	str  = _T("CHScanner Copyright (C) 2010 Calin Radoni\n");
	str += _T("This program comes with ABSOLUTELY NO WARRANTY; for details click the GPL button.\n");
	str += _T("This is free software, and you are welcome to redistribute it\n");
	str += _T("under certain conditions; click the GPL button for details.");

	staGPL.SetWindowText(str);
	staGPL.changeTextColor = true;
	staGPL.textColor = skin.titleColor;
}

//---------------------------------------------------------------------------

void DlgMain::ShowLoadedInfoCounters(void)
{
	CString str;
	int cnt;

	cnt = vendorList.GetSize();
	str.Format(_T("    Known vendors: %d"), cnt);
	display.DisplayStatusMessage(str);

	cnt = portDescList.GetSize();
	str.Format(_T("    Known ports and protocols: %d"), cnt);
	display.DisplayStatusMessage(str);

	cnt = mcast4NamesList.GetSize();
	str.Format(_T("    Known multicast IPv4 addresses assignments: %d"), cnt);
	display.DisplayStatusMessage(str);
}

//---------------------------------------------------------------------------

void DlgMain::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
//		CDialog::OnPaint();

		CPaintDC dc(this); // device context for painting

		// Do not call CDialog::OnPaint() for painting messages !!!

		RECT rect;
		CBrush brush;

		GetWindowRect(&rect);
		brush.CreateSolidBrush(skin.backColor);
		rect.right -= rect.left;
		rect.bottom -= rect.top;
		rect.left = 0;
		rect.top = 0;
		dc.FillRect(&rect, &brush);
		brush.DeleteObject();
	}
}

//---------------------------------------------------------------------------

HCURSOR DlgMain::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

//---------------------------------------------------------------------------

bool DlgMain::CreateSplashDialog(void)
{
	BOOL res;

	if(dlgSplash!=NULL)
		DestroySplashDialog();

	try{
		dlgSplash = new DlgSplash(this);
	}
	catch(...){
		dlgSplash = NULL;
	}
	if(dlgSplash==NULL) return false;

//	res = dlgSplash->Create(IDD_DLG_SPLASH, this);
	res = dlgSplash->Create(IDD_DLG_SPLASH, NULL);
	if(!res){
		delete dlgSplash;
		dlgSplash = NULL;
		return false;
	}

	res = dlgSplash->SetWindowPos(&CWnd::wndTopMost, 0, 0, 400, 100, SWP_NOMOVE | SWP_SHOWWINDOW);
	if(!res){
		DestroySplashDialog();
		return false;
	}

	return true;
}

void DlgMain::DestroySplashDialog(void)
{
	if(dlgSplash!=NULL){
		dlgSplash->DestroyWindow();
		delete dlgSplash;
		dlgSplash = NULL;
	}
}

//---------------------------------------------------------------------------

bool DlgMain::LoadConfiguration(void)
{
	CString str;
	bool res;

	config.Initialize();

	str = applicationPath;
	str += "config.dat";
	res = config.LoadFromFile(str);
	if(!res){
		display.DisplayMessageBoxById(UNABLE_TO_LOAD_CONFIGURATION, MB_OK | MB_ICONINFORMATION);
		config.Initialize();
		return false;
	}

	configInterface.applicationPath = applicationPath;
	configInterface.LoadFromFile();

	return true;
}

bool DlgMain::SaveConfiguration(void)
{
	CString str;
	CRect rect;
	bool res;

	if(dlgMap!=NULL){
		dlgMap->GetWindowRect(&rect);
		config.mapWndRect.left   = rect.left;
		config.mapWndRect.top    = rect.top;
		config.mapWndRect.right  = rect.right;
		config.mapWndRect.bottom = rect.bottom;
	}
	if(dlgMsg!=NULL){
		dlgMsg->GetWindowRect(&rect);
		config.msgWndRect.left   = rect.left;
		config.msgWndRect.top    = rect.top;
		config.msgWndRect.right  = rect.right;
		config.msgWndRect.bottom = rect.bottom;
	}
	if(dlgDetails!=NULL){
		dlgDetails->GetWindowRect(&rect);
		config.detailsWndRect.left   = rect.left;
		config.detailsWndRect.top    = rect.top;
		config.detailsWndRect.right  = rect.right;
		config.detailsWndRect.bottom = rect.bottom;
	}

	config.scanSelCfgWndRect.left   = 0;
	config.scanSelCfgWndRect.top    = 0;
	config.scanSelCfgWndRect.right  = dlgSelScanCfg.lastWidth;
	config.scanSelCfgWndRect.bottom = dlgSelScanCfg.lastHeight;

	str = applicationPath;
	str += "config.dat";
	res = config.SaveToFile(str);

	configInterface.applicationPath = applicationPath;
	configInterface.SaveToFile();

	return res;
}

//---------------------------------------------------------------------------

bool DlgMain::LoadIpLocatorBinData(void)
{
	CString str;
	bool res;
	//DWORD ts;

	if(ipLocatorBin.xDataLoaded) return true;

	//ts = GetTickCount();

	str = applicationPath;
	str += "ipLoc.dat";
	res = ipLocatorBin.LoadFromFile(str, 10);
	if(res){
		//ipLocatorBin.Sort(); // allready sorted by the import step
		ipLocatorBin.FindMiddleValue();
	}
	ipLocatorBin.xDataLoaded = res;
	
	/*
	ts = GetTickCount() - ts;
	ts = ts;
	
	str = ipLocatorBin.GetCountry(htonl(2308243456));		// CA
	str = ipLocatorBin.GetCountry(htonl(1539755263));		// DK
	str = ipLocatorBin.GetCountry(htonl(973078529));		// JP
	str = ipLocatorBin.GetCountry(htonl(3740925957));		// TW
	str = str;
	*/

	return res;
}

//---------------------------------------------------------------------------

bool DlgMain::LoadCurrentSkin(void)
{
	CString str;
	bool res;

	str = applicationPath;
	str += _T("Skins\\");
	str += config.theSkin;
	res = skin.LoadFromFile(str, _T("skin.txt"));
	if(!res){
		display.DisplayMessageBoxById(UNABLE_TO_LOAD_THE_SKIN, MB_OK | MB_ICONEXCLAMATION);
	}

	return true;
}

//---------------------------------------------------------------------------

bool DlgMain::CreateUI(void)
{
	bool res;

	res  = true;

	res &= CreateMapDialog();
	res &= CreateMsgDialog();
	res &= CreateDetailsDialog();

	if(dlgMap!=NULL)
		dlgMap->dlgDet = dlgDetails;

/*
	commandPanel.style            = MCCPanel::__pnsRaised;
	commandPanel.useSystemColors  = false;
	commandPanel.backColor        = RGB(0x60, 0x60, 0x60);
	commandPanel.highlightColor   = RGB(0x80, 0x80, 0x80);
	commandPanel.shadowColor      = RGB(0x40, 0x40, 0x40);
	commandPanel.caption          = _T("");
	result = commandPanel.SubclassDlgItem(IDC_COMMAND_PANEL, this);
	if(!result) res = false;
*/

/*
	bevel1.style           = MCCBevel::__bvsHorizontal;
	bevel1.raised          = false;
	bevel1.useSystemColors = false;
	bevel1.SubclassDlgItem(IDC_ABEVEL1, this);
*/

	return res;
}

void DlgMain::DestroyUI(void)
{
	DestroyDetailsDialog();
	DestroyMapDialog();
	DestroyMsgDialog();
}

//---------------------------------------------------------------------------

bool DlgMain::CreateMapDialog(void)
{
	BOOL res;

	if(dlgMap!=NULL)
		DestroyMapDialog();

	try{
		dlgMap = new DlgMap(this);
	}
	catch(...){
		dlgMap = NULL;
	}
	if(dlgMap==NULL) return false;

	res = dlgMap->Create(IDD_DLG_MAP, this);
	if(!res){
		delete dlgMap;
		dlgMap = NULL;
		return false;
	}

	res = dlgMap->SetWindowPos(
						NULL,
						config.mapWndRect.left,
						config.mapWndRect.top,
						config.mapWndRect.Width(),
						config.mapWndRect.Height(),
						SWP_NOZORDER | SWP_SHOWWINDOW);
	if(!res){
		DestroyMapDialog();
		return false;
	}

	dlgMap->SetProperties(&skin, true, _T("Map"));
	dlgMap->SetHelpInfo(&helpInfo, HELPID_DLG_MAP);

	return true;
}

void DlgMain::DestroyMapDialog(void)
{
	if(dlgMap!=NULL){
		dlgMap->DestroyWindow();
		delete dlgMap;
		dlgMap = NULL;
	}
}

//---------------------------------------------------------------------------

bool DlgMain::CreateMsgDialog(void)
{
	BOOL res;

	if(dlgMsg!=NULL)
		DestroyMsgDialog();

	try{
		dlgMsg = new DlgMsg(this);
	}
	catch(...){
		dlgMsg = NULL;
	}
	if(dlgMsg==NULL) return false;

	res = dlgMsg->Create(IDD_DLG_MSG, this);
	if(!res){
		delete dlgMsg;
		dlgMsg = NULL;
		return false;
	}

	res = dlgMsg->SetWindowPos(
						NULL,
						config.msgWndRect.left,
						config.msgWndRect.top,
						config.msgWndRect.Width(),
						config.msgWndRect.Height(),
						SWP_NOZORDER | SWP_SHOWWINDOW);
	if(!res){
		DestroyMsgDialog();
		return false;
	}

	dlgMsg->SetProperties(&skin, true, _T("Messages"));
	dlgMsg->SetHelpInfo(&helpInfo, HELPID_DLG_MSG);

	return true;
}

void DlgMain::DestroyMsgDialog(void)
{
	if(dlgMsg!=NULL){
		dlgMsg->DestroyWindow();
		delete dlgMsg;
		dlgMsg = NULL;
	}
}

//---------------------------------------------------------------------------

bool DlgMain::CreateDetailsDialog(void)
{
	BOOL res;

	if(dlgDetails!=NULL)
		DestroyDetailsDialog();

	try{
		dlgDetails = new DlgDetails(this);
	}
	catch(...){
		dlgDetails = NULL;
	}
	if(dlgDetails==NULL) return false;

	res = dlgDetails->Create(IDD_DLG_DETAILS, this);
	if(!res){
		delete dlgDetails;
		dlgDetails = NULL;
		return false;
	}

	res = dlgDetails->SetWindowPos(
						NULL,
						config.detailsWndRect.left,
						config.detailsWndRect.top,
						config.detailsWndRect.Width(),
						config.detailsWndRect.Height(),
						SWP_NOZORDER | SWP_SHOWWINDOW);
	if(!res){
		DestroyDetailsDialog();
		return false;
	}

	dlgDetails->SetProperties(&skin, true, _T("Details"));
	dlgDetails->SetHelpInfo(&helpInfo, HELPID_DLG_DET);

	return true;
}

void DlgMain::DestroyDetailsDialog(void)
{
	if(dlgDetails!=NULL){
		dlgDetails->DestroyWindow();
		delete dlgDetails;
		dlgDetails = NULL;
	}
}

//---------------------------------------------------------------------------

void DlgMain::PositionUiElements(void)
{
	CRect wndRect;
	CRect btnRect;
	CRect staRect;
	int posX, posY, dx, dy, dq;
	int ySpace, yPos;

	if(firstTime){
		firstTime = false;
	}
	else{
		if(!IsWindowVisible()) return;
	}

	dx = 8;
	dy = 8;

	GetWindowRect(&wndRect);
	
	posX = wndRect.Width() - dx - 100;
	posY = dy;

	yPos = posY + 10;
	ySpace = 30;

	uiBtnScan.GetWindowRect(&btnRect);
	uiBtnScan.MoveWindow(posX, yPos, btnRect.Width(), btnRect.Height(), TRUE);
	yPos += ySpace;

	uiBtnSniff.GetWindowRect(&btnRect);
	uiBtnSniff.MoveWindow(posX, yPos, btnRect.Width(), btnRect.Height(), TRUE);
	yPos += ySpace;

	uiBtnHunt.GetWindowRect(&btnRect);
	uiBtnHunt.MoveWindow(posX, yPos, btnRect.Width(), btnRect.Height(), TRUE);
	yPos += ySpace;

	uiBtnStop.GetWindowRect(&btnRect);
	uiBtnStop.MoveWindow(posX, yPos, btnRect.Width(), btnRect.Height(), TRUE);
	yPos += ySpace;

	uiBtnExpXML.GetWindowRect(&btnRect);
	uiBtnExpXML.MoveWindow(posX, yPos, btnRect.Width(), btnRect.Height(), TRUE);
	yPos += ySpace;

	uiBtnIntf.GetWindowRect(&btnRect);
	uiBtnIntf.MoveWindow(posX, yPos, btnRect.Width(), btnRect.Height(), TRUE);
	yPos += ySpace;

	uiBtnTools.GetWindowRect(&btnRect);
	uiBtnTools.MoveWindow(posX, yPos, btnRect.Width(), btnRect.Height(), TRUE);
	yPos += ySpace;

	uiBtnHelp.GetWindowRect(&btnRect);
	uiBtnHelp.MoveWindow(posX, yPos, btnRect.Width(), btnRect.Height(), TRUE);
	yPos += ySpace;

	dq = btnRect.Width();

	uiBtnClose.GetWindowRect(&btnRect);
	uiBtnClose.MoveWindow(posX, yPos, btnRect.Width(), btnRect.Height(), TRUE);
	yPos += ySpace;

	uiBtnMinimize.GetWindowRect(&btnRect);
	dq -= btnRect.Width();
	uiBtnMinimize.MoveWindow(posX + dq, yPos, btnRect.Width(), btnRect.Height(), TRUE);

	yPos += ySpace;
	uiBtnGPL.GetWindowRect(&btnRect);
	dq = btnRect.Width() - 90;
	dq /= 2;
	uiBtnGPL.MoveWindow(posX + dq, yPos, 90, 47, TRUE);

	staInfo.GetWindowRect(&staRect);
	posX = wndRect.Width() - staRect.Width();
	posX /= 2;
	posY = wndRect.Height() - staRect.Height() - 38;
	staInfo.MoveWindow(posX, posY, staRect.Width(), staRect.Height(), TRUE);

	staGPL.GetWindowRect(&staRect);
	posX = dx;
	posY = dy;
	staGPL.MoveWindow(posX, posY, staRect.Width(), staRect.Height(), TRUE);

	staInfo.Invalidate(TRUE);
	staGPL.Invalidate(TRUE);

	uiBtnScan.Invalidate(TRUE);
	uiBtnSniff.Invalidate(TRUE);
	uiBtnHunt.Invalidate(TRUE);
	uiBtnStop.Invalidate(TRUE);
	uiBtnExpXML.Invalidate(TRUE);
	uiBtnIntf.Invalidate(TRUE);
	uiBtnTools.Invalidate(TRUE);
	uiBtnHelp.Invalidate(TRUE);
	uiBtnClose.Invalidate(TRUE);
	uiBtnMinimize.Invalidate(TRUE);
	uiBtnGPL.Invalidate(TRUE);
}

void DlgMain::OnSize(UINT nType, int cx, int cy)
{
	CDialog::OnSize(nType, cx, cy);

	PositionUiElements();
}

//---------------------------------------------------------------------------

void DlgMain::SetUiScanStarted(void)
{
	uiBtnHunt.EnableWindow(FALSE);
	uiBtnSniff.EnableWindow(FALSE);
	uiBtnScan.EnableWindow(FALSE);
	uiBtnStop.EnableWindow(FALSE);
	uiBtnExpXML.EnableWindow(FALSE);
	uiBtnIntf.EnableWindow(FALSE);
	uiBtnTools.EnableWindow(FALSE);
}

void DlgMain::SetUiPassiveScanStarted(void)
{
	uiBtnHunt.EnableWindow(FALSE);
	uiBtnSniff.EnableWindow(FALSE);
	uiBtnScan.EnableWindow(FALSE);
	uiBtnStop.EnableWindow(FALSE);
	uiBtnExpXML.EnableWindow(FALSE);
	uiBtnIntf.EnableWindow(FALSE);
	uiBtnTools.EnableWindow(FALSE);
}

void DlgMain::SetUiHuntScanStarted(void)
{
	uiBtnHunt.EnableWindow(FALSE);
	uiBtnSniff.EnableWindow(FALSE);
	uiBtnScan.EnableWindow(FALSE);
	uiBtnStop.EnableWindow(FALSE);
	uiBtnExpXML.EnableWindow(FALSE);
	uiBtnIntf.EnableWindow(FALSE);
	uiBtnTools.EnableWindow(FALSE);
}

void DlgMain::SetUiWait(void)
{
	uiBtnHunt.EnableWindow(FALSE);
	uiBtnSniff.EnableWindow(FALSE);
	uiBtnScan.EnableWindow(FALSE);
	uiBtnStop.EnableWindow(FALSE);
	uiBtnExpXML.EnableWindow(FALSE);
	uiBtnIntf.EnableWindow(FALSE);
	uiBtnTools.EnableWindow(FALSE);
	uiBtnHelp.EnableWindow(FALSE);
	uiBtnClose.EnableWindow(FALSE);
	uiBtnMinimize.EnableWindow(FALSE);
	uiBtnGPL.EnableWindow(FALSE);
}

void DlgMain::SetUiNormal(void)
{
	uiBtnStop.EnableWindow(FALSE);
	uiBtnHunt.EnableWindow(TRUE);
	uiBtnSniff.EnableWindow(TRUE);
	uiBtnScan.EnableWindow(TRUE);

	if(lastScanType==__lstNone) uiBtnExpXML.EnableWindow(FALSE);
	else                        uiBtnExpXML.EnableWindow(TRUE);

	uiBtnTools.EnableWindow(TRUE);

	if(interfaceCount>1){
		uiBtnIntf.EnableWindow(TRUE);
	}
	else{
		uiBtnIntf.EnableWindow(FALSE);
	}

	uiBtnHelp.EnableWindow(TRUE);
	uiBtnClose.EnableWindow(TRUE);
	uiBtnMinimize.EnableWindow(TRUE);
	uiBtnGPL.EnableWindow(TRUE);
}

//---------------------------------------------------------------------------

void DlgMain::BeepItUp(void)
{
	if(config.completionBeep)
		MessageBeep(MB_OK);
}

//---------------------------------------------------------------------------

bool DlgMain::WaitForScanToFinish(void)
{
	bool done;

	theScanner.Stop();

	done = false;
	while(!done){
		done = !theScanner.IsRunning();
		if(!done){
			WaitForSingleObjectEx(this, 1, TRUE);
			done = !theScanner.IsRunning();
			AfxGetApp()->PumpMessage();
		}
	}

	return true;
}

//---------------------------------------------------------------------------

void DlgMain::OnBnClickedBtnScan()
{
	CString str;
	int res;

	dlgSelScanCfg.wcm        = &wcm;
	dlgSelScanCfg.skinIn     = &skin;
	dlgSelScanCfg.lastWidth  = config.scanSelCfgWndRect.right;
	dlgSelScanCfg.lastHeight = config.scanSelCfgWndRect.bottom;
	dlgSelScanCfg.SetHelpInfo(&helpInfo, HELPID_DLG_SCANSEL);
	dlgSelScanCfg.DoModal();
	config.scanSelCfgWndRect.right  = dlgSelScanCfg.lastWidth;
	config.scanSelCfgWndRect.bottom = dlgSelScanCfg.lastHeight;
	if(!dlgSelScanCfg.retVal) return;

	theScanner.msgWnd = m_hWnd;

	SetUiScanStarted();

	lastScanType = __lstActive;

	workCfg.LoadFromPointer(&dlgSelScanCfg.wcResult);

	dlgMap->UpdateInfo(NULL);

	theScanner.automaticMode = false;
	res = theScanner.Start(&workCfg);
	if(res<0){
		display.DisplayStatusMessageWithParam(SCAN_FAILED, res);
		SetUiNormal();
		return;
	}

	uiBtnStop.EnableWindow(TRUE);
}

void DlgMain::OnBnClickedBtnSniff()
{
	CString str;
	int res;

	theScanner.msgWnd = m_hWnd;

	SetUiPassiveScanStarted();

	lastScanType = __lstPasive;

	workCfg.Initialize();
	workCfg.xPassiveMode = true;

	dlgMap->UpdateInfo(NULL);

	theScanner.automaticMode = false;
	res = theScanner.Start(&workCfg);
	if(res<0){
		display.DisplayStatusMessageWithParam(SCAN_FAILED, res);
		SetUiNormal();
		return;
	}

	uiBtnStop.EnableWindow(TRUE);
}

void DlgMain::OnBnClickedBtnHunt()
{
	CString str;
	int res;

	dlgHunt.skinIn = &skin;
	dlgHunt.SetHelpInfo(&helpInfo, HELPID_DLG_HUNT);
	dlgHunt.xHuntParams.LoadFromPointer(&xHuntParams);
	dlgHunt.DoModal();
	if(!dlgHunt.retVal) return;

	SetUiHuntScanStarted();

	xHuntParams.LoadFromPointer(&dlgHunt.xHuntParams);
	if(xHuntParams.xFindLocation){
		if(xHuntParams.xIpLocator!=NULL){
			if(!xHuntParams.xIpLocator->xDataLoaded){
				display.DisplayStatusMessageForMsg(CHS_MSG_HUNT_INFO, 1, 0);
				LoadIpLocatorBinData();
			}
			if(xHuntParams.xIpLocator->xDataLoaded) display.DisplayStatusMessageForMsg(CHS_MSG_HUNT_INFO, 2, xHuntParams.xIpLocator->GetSize());
			else                                    display.DisplayStatusMessageForMsg(CHS_MSG_HUNT_INFO, 3, 0);
		}
	}

	theScanner.msgWnd = m_hWnd;
	theScanner.xHuntParams.LoadFromPointer(&xHuntParams);

	lastScanType = __lstHunt;

	workCfg.Initialize();
	workCfg.xHuntMode = true;

	dlgMap->UpdateInfo(NULL);

	theScanner.automaticMode = false;
	res = theScanner.Start(&workCfg);
	if(res<0){
		display.DisplayStatusMessageWithParam(SCAN_FAILED, res);
		SetUiNormal();
		return;
	}

	uiBtnStop.EnableWindow(TRUE);
}

//---------------------------------------------------------------------------

void DlgMain::AutoScan(void)
{
	CString str;
	int res;

	theScanner.msgWnd = m_hWnd;

	SetUiScanStarted();

	lastScanType = __lstActive;

	dlgMap->UpdateInfo(NULL);

	theScanner.automaticMode = true;
	res = theScanner.Start(&workCfg);
	if(res<0){
		display.DisplayStatusMessageWithParam(SCAN_FAILED, res);
		SetUiNormal();
		exitCode = AUTO_END_FAILEDTOSCAN;
		EndDialog(FALSE);
		return;
	}

	uiBtnStop.EnableWindow(TRUE);
}

void DlgMain::AutoScanPassive(void)
{
	CString str;
	int res;
	UINT_PTR timerId;

	if(autoRunTime!=0){
		res = autoRunTime * 1000;
		timerId = SetTimer(TIMER_AUTO_PASSIVE, res, NULL);
		if(timerId==0){
			exitCode = AUTO_END_COULDNOTSETTIMER;
			EndDialog(FALSE);
			return;
		}
	}

	theScanner.msgWnd = m_hWnd;

	SetUiPassiveScanStarted();

	lastScanType = __lstPasive;

	dlgMap->UpdateInfo(NULL);

	theScanner.automaticMode = true;
	res = theScanner.Start(&workCfg);
	if(res<0){
		display.DisplayStatusMessageWithParam(SCAN_FAILED, res);
		SetUiNormal();
		KillTimer(TIMER_AUTO_PASSIVE);
		exitCode = AUTO_END_FAILEDTOSCAN;
		EndDialog(FALSE);
		return;
	}

	uiBtnStop.EnableWindow(TRUE);
}

//---------------------------------------------------------------------------

void DlgMain::OnBnClickedBtnStop()
{
	uiBtnStop.EnableWindow(FALSE);

	theScanner.Stop();

	display.DisplayStatusMessage(STOP_COMMAND_HAS_BEEN_SENT);
}

//---------------------------------------------------------------------------

void DlgMain::OnBnClickedBtnExpXML()
{
	CString strName;
	CString strTime;
	CString str;
	bool res;

	if(dlgMap==NULL){
		exitCode = END_EXPORT_FAILED;
		return;
	}

	strTime = theScanner.GetStartTime();
	if(strTime.IsEmpty()){
		// NO scan has been performed -> nothing to export
		exitCode = END_EXPORT_FAILED;
		return;
	}

	strName  = applicationPath;
	strName += theScanner.GetNameFromTime();
	strName += _T(".xml");

	exitExportedFile = strName;

	switch(lastScanType){
		case __lstActive :
			res = dlgMap->ExportAsXml(strName, strTime, &workCfg, lastScanType);
			break;

		case __lstPasive :
			res = dlgMap->ExportAsXml(strName, strTime, NULL, lastScanType);
			break;

		case __lstHunt :
			res = dlgMap->ExportAsXml(strName, strTime, NULL, lastScanType);
			break;

		default:
			res = false;
			break;
	}

	str.Format(_T("XML export to file \"%s\" has "), strName);
	if(res) str += _T("succedded.");
	else{
		exitCode = END_EXPORT_FAILED;
		str += _T("FAILED !");
	}

	if(dlgMsg!=NULL)
		dlgMsg->AddMessage(str);
}

//---------------------------------------------------------------------------

void DlgMain::OnBnClickedBtnIntf()
{
	dlgInterface.skinIn = &skin;
	dlgInterface.SetHelpInfo(&helpInfo, HELPID_DLG_INTF);
	dlgInterface.DoModal();

	if(!dlgInterface.intfName.IsEmpty()){
		configInterface.interfaceName = dlgInterface.intfName;
		SetWorkInterfaceAndDisplayInfo();
	}
}

//---------------------------------------------------------------------------

void DlgMain::OnBnClickedBtnTools()
{
	RECT rect;
	int hh;

	if(!popupMenu.IsCreated()) return;

	uiBtnTools.GetWindowRect(&rect);
	hh = rect.bottom - rect.top;
	popupMenu.Show(this, rect.left + hh, rect.top + hh);
}

//---------------------------------------------------------------------------

void DlgMain::OnBnClickedBtnHelp()
{
	helpInfo.ShowHelp(HELPID_INDEX);
}

//---------------------------------------------------------------------------

void DlgMain::OnBnClickedBtnClose()
{
	WaitForScanToFinish();

	if(!SaveConfiguration())
		display.DisplayMessageBoxById(UNABLE_TO_SAVE_CONFIGURATION, MB_OK | MB_ICONEXCLAMATION);

	exitCode = AUTO_END_SUCCESS;

	EndDialog(TRUE);
}

//---------------------------------------------------------------------------

void DlgMain::OnBnClickedBtnMinimize()
{
	ShowWindow(SW_MINIMIZE);
}

//---------------------------------------------------------------------------

void DlgMain::OnBnClickedBtnGPL()
{
	helpInfo.OpenGPL();
}

//---------------------------------------------------------------------------

void DlgMain::OnCancel()
{
	// no more closing on this event !
//	CDialog::OnCancel();
}

void DlgMain::OnOK()
{
	// no more closing on this event !
//	CDialog::OnOK();
}

//---------------------------------------------------------------------------

void DlgMain::OnShowWindow(BOOL bShow, UINT nStatus)
{
	CDialog::OnShowWindow(bShow, nStatus);

	if(bShow){
		firstTime = true;
		PositionUiElements();
	}
}

//---------------------------------------------------------------------------

LRESULT DlgMain::OnCmsStart(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_SCAN_START, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsDone(WPARAM wpIn, LPARAM lpIn)
{
	switch(autoRunMode){
		case __rmNormal :
			SetUiNormal();
			BeepItUp();
			break;

		case __rmAutoScan :
		case __rmPassive :
			KillTimer(TIMER_AUTO_PASSIVE);
			WaitForScanToFinish();
			OnBnClickedBtnExpXML();
			// exitCode is set on OnBnClickedBtnExpXML !!!

			exitRunningTime = display.GetTime((DWORD)lpIn);

			PostMessage(CHS_MSG_AUTOCLOSE, (WPARAM)0, (LPARAM)0);
			return 1;
	}
	
	return display.DisplayStatusMessageForMsg(CHS_MSG_SCAN_DONE, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsSkipped(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_SCAN_SKIPPED, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsRandomizeAddrList(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_SCAN_RANDOMIZE_ADDRLIST, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsSortAddrList(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_SCAN_SORT_ADDRLIST, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsPhaseStart(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_SCANPHASE_START, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsPhaseDone(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_SCANPHASE_DONE, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsPhaseFailed(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_SCANPHASE_FAILED, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsPhaseSkipped(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_SCANPHASE_SKIPPED, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsAfterPhase(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_AFTER_PHASE, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsListBuilded(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_LIST_BUILDED, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsUpdateData(WPARAM wpIn, LPARAM lpIn)
{
	switch(wpIn){
		case 0 :
			if(dlgMap!=NULL)
				dlgMap->UpdateInfo(theScanner.GetMachInfoList());
			break;

		case 1 :
			if(dlgMap!=NULL)
				dlgMap->UpdateInfoEx(theScanner.GetMachInfoList(), true);
			break;

		case 2 :
			if(dlgMap!=NULL)
				dlgMap->UpdateInfoEx(theScanner.GetMachInfoList(), false);
			break;
	}

	dlgMap->SetActiveWindow();

	return 1;
}

LRESULT DlgMain::OnCmsPacketsSent(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_PACKETS_SENT, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsMethodStart(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_METHOD_START, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsMethodAbort(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_METHOD_ABORT, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsMethodSARPUpd(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_SYSARPTAB_UPDATED, wpIn, lpIn) ? 1 : 0;
}

LRESULT DlgMain::OnCmsHuntMachine(WPARAM wpIn, LPARAM lpIn)
{
	return display.DisplayStatusMessageForMsg(CHS_MSG_HUNT_MACHINE, wpIn, lpIn) ? 1 : 0;
}

//---------------------------------------------------------------------------

LRESULT DlgMain::OnCmsAutoRun(WPARAM wpIn, LPARAM lpIn)
{
	switch(autoRunMode){
		case __rmAutoScan :
			AutoScan();
			break;

		case __rmPassive :
			AutoScanPassive();
			break;
	}

	return 1;
}


LRESULT DlgMain::OnCmsAutoClose(WPARAM wpIn, LPARAM lpIn)
{
	switch(autoRunMode){
		case __rmAutoScan :
		case __rmPassive :
			EndDialog(TRUE);
			return 1;
	}

	return 1;
}

//---------------------------------------------------------------------------

LRESULT DlgMain::OnKickIdle(WPARAM, LPARAM lCount)
{
	// TODO this can be removed BUT NOT before writting a guide about it !!!

	// do not return TRUE because the message will be sent again and again and again ...
	return FALSE;
}

//---------------------------------------------------------------------------

BOOL DlgMain::OnHelpInfo(HELPINFO* pHelpInfo)
{
	if(pHelpInfo==NULL) return FALSE;

	helpInfo.ShowHelp(HELPID_DLG_MAIN);

	return TRUE;
}

//---------------------------------------------------------------------------

void DlgMain::OnTimer(UINT_PTR nIDEvent)
{
	switch(nIDEvent){
		case TIMER_AUTO_PASSIVE :
			KillTimer(TIMER_AUTO_PASSIVE);
			OnBnClickedBtnStop();
			break;
	}

	CDialog::OnTimer(nIDEvent);
}

//---------------------------------------------------------------------------

BOOL DlgMain::OnCommand(WPARAM wParam, LPARAM lParam)
{
	if(lParam!=0)
		return CDialog::OnCommand(wParam, lParam);

	WORD val;
	val = HIWORD(wParam);
	if(val!=0){
		// not from a menu
		return CDialog::OnCommand(wParam, lParam);
	}

	val = LOWORD(wParam);
	ProcessMenuItemCommand(val);

	return TRUE;
}

//---------------------------------------------------------------------------

void DlgMain::ProcessMenuItemCommand(WORD menuItemIdIn)
{
	switch(menuItemIdIn){
		case MI_MACLookup :
			ToolsMACLookup();
			break;

		case MI_MCASTLookup :
			ToolsMcast4Lookup();
			break;

		case MI_Config :
			ToolsConfigureApplication();
			break;

		case MI_ResetLayout :
			ToolsResetLayout();
			break;

		case MI_UpdateCheck :
			ToolsCheckForUpdates();
			break;

		case MI_ImportGeoIP :
			ToolsImportGeoIP();
			break;

		default:
			break;
	}
}

//---------------------------------------------------------------------------

void DlgMain::ToolsMACLookup(void)
{
	CString str;
	MAddressMAC  macAddr;
	MAddressIP   ipAddr;
	MAddressIPv6 ipAddr6;
	MArpCacheList *arpCacheList;


/*
	// This is the TEST vector !
	// DO NOT DELETE IT !!!!!!!!

	macAddr.LoadFromString(_T("00:00:5E:00:00:17"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("00:00:5E:00:01:17"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("00:00:5E:00:36:17"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("00:00:5E:01:00:17"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("01:00:5E:01:00:17"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("01:00:5E:80:00:17"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("01:80:C2:00:00:20"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("01:80:C2:00:00:21"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("01:80:C2:00:00:22"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("33:33:00:00:00:01"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("33:33:00:00:00:02"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("33:33:01:23:45:67"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("FF:FF:FF:FF:FF:FF"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("00:00:00:00:00:00"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("00:00:CD:12:34:56"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("01:E0:FE:12:34:56"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	macAddr.LoadFromString(_T("20:20:20:20:20:20"));OutputDebugString(vendorList.GetVendorName_MACLookup(&macAddr));OutputDebugString(_T("\n"));
	return;
*/

	dlgEdit.skinIn = &skin;
	dlgEdit.infoString = _T("Enter MAC:");
	dlgEdit.dataString.Empty();
	dlgEdit.SetHelpInfo(&helpInfo, HELPID_EDIT_MACLOOKUP);
	dlgEdit.DoModal();
	if(!dlgEdit.retVal) return;

	str = dlgEdit.dataString;
	if(!macAddr.LoadFromString(str)){
		display.DisplayStatusMessage(MAC_ADDRESS_WRONG_SPEC);
		return;
	}

	str = vendorList.GetVendorName_MACLookup(&macAddr);
	display.DisplayStatusMessage(str);

	arpCacheList = theScanner.GetArpCacheList();

	if(applicationPath.IsEmpty()) return;
	str = applicationPath;
	str += _T("arpCache.dat");
	arpCacheList->LoadFromFile(str);

	DWORD ipv4;
	if(arpCacheList->GetIPv4ByMac(&macAddr, &ipv4)) str = _T("MAC not found in cache for IPv4.");
	else{
		ipAddr.Set(ipv4);
		str.Format(_T("In cache, MAC %s is for the %s IP address."), macAddr.GetS(), ipAddr.GetS());
	}
	display.DisplayStatusMessage(str);

	in_addr6 ipv6;
	if(arpCacheList->GetIPv6ByMac(&macAddr, &ipv6)) str = _T("MAC not found in cache for IPv6.");
	else{
		ipAddr6.Set(&ipv6);
		str.Format(_T("In cache, MAC %s is for the %s IPv6 address."), macAddr.GetS(), ipAddr6.GetS());
	}
	display.DisplayStatusMessage(str);
}

//---------------------------------------------------------------------------

void DlgMain::ToolsMcast4Lookup(void)
{
	CString ipIn;
	MAddressIP ipAddr;
	in_addr ia;

	dlgEdit.skinIn = &skin;
	dlgEdit.infoString = _T("Enter multicast IPV4 address:");
	dlgEdit.dataString.Empty();
	dlgEdit.SetHelpInfo(&helpInfo, HELPID_EDIT_MCAST4LOOK);
	dlgEdit.DoModal();
	if(!dlgEdit.retVal) return;

	ipIn = dlgEdit.dataString;
	ipAddr.Set(ipIn);
	ia.S_un.S_addr = ipAddr.GetD();
	if(ia.S_un.S_un_b.s_b1<224 || ia.S_un.S_un_b.s_b1>239){
		display.DisplayStatusMessage(MCAST4_ADDRESS_WRONG_SPEC);
		return;
	}

	ipIn = mcast4NamesList.GetName(ipAddr.GetD(), false);
	if(ipIn.IsEmpty()) display.DisplayStatusMessageWithParamS(MCAST4_ADDRESS_ASSIGNED_NF, ipAddr.GetS());
	else               display.DisplayStatusMessageWithParamSS(MCAST4_ADDRESS_ASSIGNED, ipAddr.GetS(), ipIn);
}

//---------------------------------------------------------------------------

void DlgMain::ToolsConfigureApplication(void)
{
	dlgConfig.skinIn = &skin;
	dlgConfig.SetHelpInfo(&helpInfo, HELPID_DLG_CONFIG);
	dlgConfig.config.LoadFromPointer(&config);
	dlgConfig.DoModal();
	if(!dlgConfig.retVal) return;

	config.LoadFromPointer(&(dlgConfig.config));
	display.DisplayStatusMessage(CONFIGURATION_UPDATED);

	SaveConfiguration();
}

//---------------------------------------------------------------------------

void DlgMain::ToolsResetLayout(void)
{
	MConfig newConfig;
	BOOL res;

	newConfig.Initialize();

	config.mapWndRect.left          = newConfig.mapWndRect.left;
	config.mapWndRect.top           = newConfig.mapWndRect.top;
	config.mapWndRect.right         = newConfig.mapWndRect.right;
	config.mapWndRect.bottom        = newConfig.mapWndRect.bottom;

	config.msgWndRect.left          = newConfig.msgWndRect.left;
	config.msgWndRect.top           = newConfig.msgWndRect.top;
	config.msgWndRect.right         = newConfig.msgWndRect.right;
	config.msgWndRect.bottom        = newConfig.msgWndRect.bottom;

	config.detailsWndRect.left      = newConfig.detailsWndRect.left;
	config.detailsWndRect.top       = newConfig.detailsWndRect.top;
	config.detailsWndRect.right     = newConfig.detailsWndRect.right;
	config.detailsWndRect.bottom    = newConfig.detailsWndRect.bottom;

	config.scanSelCfgWndRect.left   = newConfig.scanSelCfgWndRect.left;
	config.scanSelCfgWndRect.top    = newConfig.scanSelCfgWndRect.top;
	config.scanSelCfgWndRect.right  = newConfig.scanSelCfgWndRect.right;
	config.scanSelCfgWndRect.bottom = newConfig.scanSelCfgWndRect.bottom;

	res = TRUE;

	if(dlgMap!=NULL){
		res &= dlgMap->SetWindowPos(
							NULL,
							config.mapWndRect.left,
							config.mapWndRect.top,
							config.mapWndRect.Width(),
							config.mapWndRect.Height(),
							SWP_NOZORDER | SWP_SHOWWINDOW);
		dlgMap->SetProperties(&skin, true, _T("Map"));
	}

	if(dlgMsg!=NULL){
		res &= dlgMsg->SetWindowPos(
							NULL,
							config.msgWndRect.left,
							config.msgWndRect.top,
							config.msgWndRect.Width(),
							config.msgWndRect.Height(),
							SWP_NOZORDER | SWP_SHOWWINDOW);
		dlgMsg->SetProperties(&skin, true, _T("Messages"));
	}

	if(dlgDetails!=NULL){
		res &= dlgDetails->SetWindowPos(
							NULL,
							config.detailsWndRect.left,
							config.detailsWndRect.top,
							config.detailsWndRect.Width(),
							config.detailsWndRect.Height(),
							SWP_NOZORDER | SWP_SHOWWINDOW);
		dlgDetails->SetProperties(&skin, true, _T("Details"));
	}

	if(res){
		// layout has been reset
		display.DisplayStatusMessage(LAYOUT_RESET);
	}
	else{
		// failed to reset layout
		display.DisplayStatusMessage(LAYOUT_RESET_FAILED);
	}
}

//---------------------------------------------------------------------------

void DlgMain::ToolsCheckForUpdates(void)
{
	CString str;
	int res;

	SetUiWait();

	// http://chscanner.googlecode.com/files/verCHS.html
	res = updateCheck.Check("chscanner.googlecode.com", "/files/verCHS.html");

	if(res<0){
		// failed to check for updates
		str.Format(_T("Failed to check for updates (error code %d)!"), res);
		display.DisplayStatusMessage(str);
		SetUiNormal();
		return;
	}

	if(res==0){
		// No Updates Found: There are no new updates available
		display.DisplayStatusMessage(_T("There are no new updates available."));
		SetUiNormal();
		return;
	}

	// update found
	str.Format(_T("The version %s is available."), updateCheck.xVersionFound.c_str());
	display.DisplayStatusMessage(str);
	SetUiNormal();
}

//---------------------------------------------------------------------------

void DlgMain::ToolsImportGeoIP(void)
{
	CString str;
	bool res;
	DWORD ts;
	unsigned int cnt1, cnt2;

	SetUiWait();

	ts = GetTickCount();

	// Read the data
	str = _T("Importing data. Please wait...");
	display.DisplayStatusMessage(str);

	str = _T("... reading the GeoIP data");
	display.DisplayStatusMessage(str);
	
/*
	str = applicationPath;
	str += "ip-to-country.csv";
	res = ipLocator.ImportIpToLocation(str);
*/

	str = applicationPath;
	str += "GeoIPCountryWhois.csv";
	res = ipLocator.ImportGeoIP(str);
	if(!res){
		str = _T("... failed to read the GeoIP data!");
		display.DisplayStatusMessage(str);
		SetUiNormal();
		return;
	}

	cnt1 = (unsigned int)ipLocator.GetSize();

	str.Format(_T("... readed %d records"), cnt1);
	display.DisplayStatusMessage(str);

	// Sort the data
	str = _T("... sorting the GeoIP data");
	display.DisplayStatusMessage(str);

	ipLocator.Sort();

	str = _T("... sorted the GeoIP data");
	display.DisplayStatusMessage(str);

	// Save the data
	str = _T("... writing converted GeoIP data");
	display.DisplayStatusMessage(str);

	str = applicationPath;
	str += "ipLoc.dat";
	res = ipLocator.ExportAsBinary(str);
	if(!res){
		str = _T("... failed to write the GeoIP data!");
		display.DisplayStatusMessage(str);
		SetUiNormal();
		return;
	}

	str = _T("... the converted data was saved");
	display.DisplayStatusMessage(str);

	// Clean unneeded data
	str = _T("... cleaning memory");
	display.DisplayStatusMessage(str);

	ipLocator.Clear();

	str = _T("... memory cleaned");
	display.DisplayStatusMessage(str);

	// check converted data
	str = _T("... checking converted data");
	display.DisplayStatusMessage(str);

	str = applicationPath;
	str += "ipLoc.dat";
	res = ipLocatorBin.LoadFromFile(str, 10);
	if(!res){
		str = _T("...failed to read coverted data!");
		display.DisplayStatusMessage(str);
		SetUiNormal();
		return;
	}

	ipLocatorBin.xDataLoaded = true;

	cnt2 = ipLocatorBin.GetSize();

	str.Format(_T("... readed %d records"), cnt2);
	display.DisplayStatusMessage(str);

	ts = GetTickCount() - ts;

	if(cnt1!=cnt2){
		str.Format(_T("Failed. %.2f seconds wasted."), ((float)ts)/1000.0);
		display.DisplayStatusMessage(str);
		SetUiNormal();
		return;
	}

	str.Format(_T("Done. %.2f seconds elapsed."), ((float)ts)/1000.0);
	display.DisplayStatusMessage(str);

	/*
	str = ipLocatorBin.GetCountry(htonl(201674099));		// CA
	str = ipLocatorBin.GetCountry(htonl(1539755263));		// DK
	str = ipLocatorBin.GetCountry(htonl(973078529));		// JP
	str = ipLocatorBin.GetCountry(htonl(3560942199));		// ""
	str = str;
	*/

	SetUiNormal();
}

//---------------------------------------------------------------------------
